#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <vector>
using namespace std;
template <class T>
class ringqueue
{
private:
    void P(sem_t &_sem)
    {
        int n = sem_wait(&_sem);
        if (n != 0)
        {
            cout << strerror(errno) << endl;
        }
    }
    void V(sem_t &_sem)
    {
        int n = sem_post(&_sem);
        if (n != 0)
        {
            cout << strerror(errno) << endl;
        }
    }

public:
    ringqueue(int cap = 5) : _queue(cap), _cap(cap)
    {
        pthread_mutex_init(&_pMutex, nullptr);
        pthread_mutex_init(&_cMutex, nullptr);
        _pStep = _cStep = 0;
        sem_init(&_dateSem, 0, 0);
        sem_init(&_spaceSem, 0, _cap);
    }
    void push(const T &task)
    {
        P(_spaceSem);
        pthread_mutex_lock(&_pMutex);
        _queue[_pStep] = task;
        _pStep = (_pStep + 1) % _cap;
        pthread_mutex_unlock(&_pMutex);
        V(_dateSem);
    }
    void pop(T &task)
    {
        P(_dateSem);
        pthread_mutex_lock(&_cMutex);
        task = _queue[_cStep];
        _cStep = (_cStep + 1) % _cap;
        pthread_mutex_unlock(&_cMutex);
        V(_spaceSem);
    }
    ~ringqueue()
    {
        pthread_mutex_destroy(&_pMutex);
        pthread_mutex_destroy(&_cMutex);
        sem_destroy(&_dateSem);
        sem_destroy(&_spaceSem);
    }

private:
    vector<T> _queue;
    int _cap;
    int _pStep;
    int _cStep;
    sem_t _dateSem;
    sem_t _spaceSem;
    pthread_mutex_t _pMutex;
    pthread_mutex_t _cMutex;
};